<template>
  <div class="content">
    <div class="left">
      <div style="background: #fff; height: 100%;">
        <a-input-search @search="onSearch" style="width:100%;" placeholder="请输入搜索内容" />
        <a-spin class="tree" :spinning="loading">
          <a-tree
            :replaceFields="{title:'name', key: 'id', children:'childrenList'}"
            :treeData="treeData"
            :expandedKeys="iExpandedKeys"
            showIcon
            checkable
            @expand="onExpand"
            :autoExpandParent="autoExpandParent"
            :checkedKeys="currentSelectedLayerIds"
            @check="onCheck"
          >
            <template slot="name" slot-scope="record">
              <img
                :src="getResourceURL(record)"
                height="18px"
                width="18px"
              />
              <span style="margin-left=3px">{{record.name}}</span>
            </template>
          </a-tree>
        </a-spin>
      </div>
    </div>
    <div class="right">
      <!-- <div id="map" class="map"></div> -->
      <div class="gd">
        <MapBaseYt ref="mapBaseYt" :isShowBounds="true" @loaded="initMap" />
      </div>
    </div>
  </div>
</template>

<script>
import tempIcon from '@assets/map/icon/icon-temp.png'
import fileIcon from '@assets/map/icon/file.png'
import MapBaseYt from '@comp/map/MapBaseYt'
import { JeecgListMixin } from '@/mixins/JeecgListMixin'
import { postAction, getAction } from '@api/manage'

export default {
  name: 'GlobalMap',
  components: { MapBaseYt },
  mixins: [JeecgListMixin],
  data() {
    return {
      treeData: [],
      loading: false,
      iExpandedKeys: [],
      allTreeKeys: [],
      checkedKeys: [],
      map: null,
      layerList: [],
      autoExpandParent: true,
      POIOrdinaryLayer: {}, // poi普通图层对象参数
      POIIcon: {}, // poi普通图层图标
      POIClusterLayer: {}, // poi聚合图层对象参数
      currentLayerIdWithOpeningPopup: null,
      currentSelectedLayerIds: [],
      url: {
        mapList: '/visual/layer/mapLayerSearch',
        // list: '/visual/layer/listLayer'
        queryList: '/subject/scSubjectLayerGroup/getLeftDirectoryByGroupName',
        list: '/subject/scSubjectLayerGroup/getGroupList'
      }
    }
  },
  methods: {
    loadData() {
      this.refresh()
    },
    refresh() {
      this.loadTree(true)
    },
    loadTree(isInit = false, params = {}) {
      this.loading = true
      var that = this
      getAction(this.url.list, params)
        .then((res) => {
          if (res.success) {
            this.treeData = []
            this.allTreeKeys = []
            this.layerList = []
            const record = res.result
            for (let i = 0; i < record.length; i++) {
              const temp = record[i]
              that.dealData(temp)
            }
            if (isInit) this.initPOILayers() // 初始化参数传入时，进行poi图层初始化
          } else {
            this.$message.error(res.message)
          }
        })
        .finally(() => {
          this.loading = false
        })
    },
    getResourceURL(record) {
      var layerIcon = record.layerIcon || record.groupIcon
      return layerIcon ? `${window._CONFIG['domianURL']}/${layerIcon}` : record.isLayer ? tempIcon : fileIcon
    },
    // 处理列表的可选择，只有isLayer是true才展示checkable，只有图层可选择
    setCheckable(node) {
      node.checkable = !!node.isLayer
      var temp = node.childrenList
      if (temp && temp.length > 0) {
        for (let a = 0; a < temp.length; a++) {
          this.setCheckable(temp[a])
        }
      }
    },
    parseLayerInfoList(node) {
      const list = node.scSubjectLayerInfoList
      node.scopedSlots = { title: 'name' }
      if (list && list.length > 0) {
        for (let a = 0; a < list.length; a++) {
          const item = list[a]
          item.groupId = node.id
          item.isLayer = 1
          item.scopedSlots = { title: 'name' }
          item.name = item.layerName
          node.childrenList.push(item)
          this.layerList.push(item)
        }
      }
      if (node.childrenList && node.childrenList.length > 0) {
        for (let a = 0; a < node.childrenList.length; a++) {
          this.parseLayerInfoList(node.childrenList[a])
        }
      }
    },
    onSearch(value) {
      const that = this
      if (value) {
        getAction(this.url.queryList, { name: value }).then(res => {
          if (res.success) {
            that.treeData = []
            this.layerList = []
            const records = res.result
            for (let i = 0; i < records.length; i++) {
              const temp = records[i]
              // 如果父节点有内容，按照正常处理，如果父节点是空，则遍历
              that.dealData(temp)
            }
            // this.initPOILayers() // 初始化参数传入时，进行poi图层初始化
          } else {
            that.$message.warning(res.message)
          }
        })
      } else {
        that.loadTree()
      }
    },
    dealData(temp) {
      // if (temp.id) {
      this.parseLayerInfoList(temp)
      // } else {
      //   this.parseLayerSearchList(temp)
      // }
      this.setCheckable(temp)
      this.treeData.push(temp)
      this.setThisExpandedKeys(temp)
      this.getAllKeys(temp)
    },
    getAllKeys(node) {
      this.allTreeKeys.push(node.id)
      if (node.childrenList && node.childrenList.length > 0) {
        for (let a = 0; a < node.childrenList.length; a++) {
          this.getAllKeys(node.childrenList[a])
        }
      }
      if (node.scSubjectLayerInfoList && node.scSubjectLayerInfoList.length > 0) {
        for (let a = 0; a < node.scSubjectLayerInfoList.length; a++) {
          this.getAllKeys(node.scSubjectLayerInfoList[a])
        }
      }
    },
    setThisExpandedKeys(node) {
      if (node.childrenList && node.childrenList.length > 0) {
        this.iExpandedKeys.push(node.id)
        for (let a = 0; a < node.childrenList.length; a++) {
          this.setThisExpandedKeys(node.childrenList[a])
        }
      }
    },
    onExpand(expandedKeys) {
      // if not set autoExpandParent to false, if children expanded, parent can not collapse.
      // or, you can remove all expanded children keys.
      this.iExpandedKeys = expandedKeys
      this.autoExpandParent = false
    },
    expandAll() {
      this.iExpandedKeys = this.allTreeKeys
    },
    closeAll() {
      this.iExpandedKeys = []
    },
    initPOILayers() {
      if (!this.map) {
        setTimeout(() => {
          this.initPOILayers() // 等待地图初始化完成，延时执行
        }, 500)
        return
      }
      // 遍历图层树数据，为各poi图层初始化创建普通图层和聚合图层
      for (const item of this.layerList) {
        this.POIIcon[item.id] = item.layerIcon !== null ? `${window._CONFIG['domianURL']}/${item.layerIcon}` : tempIcon
        this.POIOrdinaryLayer[item.id] = new this.$IMap.layer.GraphicLayer() // 实例化图层对应的普通图层
        this.POIClusterLayer[item.id] = new this.$IMap.layer.ClusterLayer({
          maxClusterRadius: 40,
          showCoverageOnHover: false,
          chunkedLoading: true,
          iconCreateFunction: cluster => {
            const markers = cluster.getAllChildMarkers()
            const number = markers.length
            return this.$IMap.L.divIcon(this.createClusterIconTemplate(number, this.POIIcon[item.id]))
          }
        }) // 实例化图层对应的聚合图层(最大层级时，使用前端聚合)
        this.map.addLayer(this.POIOrdinaryLayer[item.id])
        this.map.addLayer(this.POIClusterLayer[item.id])
      }
    },
    initMap() {
      this.map = this.$refs.mapBaseYt.map
      // 事件监听初始化
      this.map.on('zoomend', () => {
        if (!this.map || this.map.dataLoading) return
        this.loadPOIData(this.currentSelectedLayerIds)
      })
      this.map.on('moveend', () => {
        if (!this.map || this.map.dataLoading) return
        this.loadPOIData(this.currentSelectedLayerIds)
      })
      this.map.on('popupopen', event => {
        this.currentLayerIdWithOpeningPopup = event.popup.options.layerId
      })
      this.map.on('popupclose', () => {
        this.currentLayerIdWithOpeningPopup = null
      })
    },
    // 图层树选择事件回调(包含勾选、取消勾选)
    onCheck(checkedKeys, event) {
      this.hiding = false
      if (event.checked) {
        // 勾选操作时
        this.loadPOIData([checkedKeys[checkedKeys.length - 1]]) // 进行勾选是图层数据加载(checkedKeys最后一项对应勾选的追加图层id)
      } else {
        // 取消勾选操作时
        const discardedKey = this.getDiscardedKey(checkedKeys, this.currentSelectedLayerIds) // 获取取消勾选的图层
        this.clearPOIDataOnLayer(discardedKey[0]) // 取消勾选的图层数据移除
      }
      console.log('checkedKeys', checkedKeys)
      this.currentSelectedLayerIds = checkedKeys // 更新当前选中图层索引数组
    },
    // 获取指定图层的POI数据
    loadPOIData(layerIds = []) {
      if (!layerIds.length) return
      let isFrontCluster = false // 前端聚合标识参数，默认为false
      if (this.map.zoom === this.map.getMaxZoom()) isFrontCluster = true // 地图处于最大层级时，更新标识参数
      const bounds = {
        topLeftPoint: this.map.getBounds().getNorthWest(),
        bottomRightPoint: this.map.getBounds().getSouthEast()
      }
      // 拼接请求参数
      const params = {
        topLeft: {
          fragment: true,
          geohash: '',
          lat: bounds.topLeftPoint.lat,
          lon: bounds.topLeftPoint.lng
        },
        layerIdList: layerIds,
        needGroup: !isFrontCluster,
        bottomRight: {
          fragment: true,
          geohash: '',
          lat: bounds.bottomRightPoint.lat,
          lon: bounds.bottomRightPoint.lng
        },
        zoomLevel: this.map.zoom
      }
      // 数据请求获取
      this.loading = true
      this.$refs.mapBaseYt.dataLoading = true
      postAction(this.url.mapList, params).then(res => {
        if (res.success) {
          this.showPOIDataOnMap(res.result, isFrontCluster) // 数据上图
        } else {
          this.$message.error(res.message)
          this.$refs.mapBaseYt.dataLoading = false
        }
      }).finally(() => {
        this.loading = false
      }).catch(() => {
        this.$refs.mapBaseYt.dataLoading = false
      })
    },
    // POI数据上图
    showPOIDataOnMap(data, isFrontCluster) {
      for (const layerId in data) {
        this.clearPOIDataOnLayer(layerId) // 清空POI数据对应的图层
        if (isFrontCluster) {
          // 前端聚合场景
          data[layerId].forEach((item) => {
            if (!this.$refs.mapBaseYt.checkLatlng(item.lat, 'lat') || !this.$refs.mapBaseYt.checkLatlng(item.lng, 'lng')) return // 坐标合法性判别
            const graphic = new this.$IMap.graphic.Marker({
              latlng: [item.lat, item.lng],
              style: {
                iconUrl: this.POIIcon[layerId],
                riseOnHover: true,
                width: 24,
                height: 24,
                iconAnchor: [12, 24], // icon锚点，相对于图片左上角偏移量
                popupAnchor: [0.00001, -24] // popup打开位置偏移(相对icon锚点竖直向上一个icon高度(水平方向设值存在bug，使用微量匹配修正))
              }
            })
            graphic.bindPopup(item.name, {
              layerId: layerId // 额外添加图层id，作为被动关闭时的判断依据
            })
            this.POIClusterLayer[layerId].addGraphic(graphic)
          })
        } else {
          // 后端聚合场景
          const markers = []
          // 遍历数据，区分聚合点和POI点
          data[layerId].forEach((item) => {
            if (!this.$refs.mapBaseYt.checkLatlng(item.lat, 'lat') || !this.$refs.mapBaseYt.checkLatlng(item.lng, 'lng')) return // 坐标合法性判别
            let graphic = null
            if (!item.isGroup) {
              // 非聚合点
              graphic = new this.$IMap.graphic.Marker({
                latlng: [item.lat, item.lng],
                style: {
                  iconUrl: this.POIIcon[layerId],
                  riseOnHover: true,
                  width: 24,
                  height: 24,
                  iconAnchor: [12, 24], // icon锚点，相对于图片左上角偏移量
                  popupAnchor: [0.00001, -24] // popup打开位置偏移(相对icon锚点竖直向上一个icon高度(水平方向设值存在bug，使用微量匹配修正))
                }
              })
              graphic.bindPopup(item.name, {
                layerId: layerId // 额外添加图层id，作为被动关闭时的判断依据
              })
            } else {
              // 聚合点
              graphic = new this.$IMap.graphic.DivGraphic({
                latlng: [item.lat, item.lng],
                style: this.createClusterIconTemplate(item.size, this.POIIcon[layerId])
              })
              graphic.on('click', event => {
                this.map.setView(event.latlng, this.map.zoom + 2)
              })
            }
            markers.push(graphic)
          })
          this.POIOrdinaryLayer[layerId].addGraphic(markers)
        }
      }
      this.$refs.mapBaseYt.dataLoading = false
    },
    // 清空指定图层的POI数据
    clearPOIDataOnLayer(POILayerId = null, type = 0) {
      if (POILayerId === null) return
      if (type === 1 || type === 0) this.POIOrdinaryLayer[POILayerId] && this.POIOrdinaryLayer[POILayerId].clear() // 指定type为0/1时，清空普通图层
      if (type === 2 || type === 0) this.POIClusterLayer[POILayerId] && this.POIClusterLayer[POILayerId].clear() // 指定type为0/2时，清空聚合图层
      if (POILayerId === this.currentLayerIdWithOpeningPopup) this.map.closePopup() // 关闭popup(若指定图层打开popup)
    },
    // 生成聚合图标(html-div)的模板方法
    createClusterIconTemplate(number, iconUrl) {
      let clusterValue = Number(number)
      if (Number(number) > 10000) clusterValue = '1万+'
      const html = `
      <div>
        <div style="line-height: 16px; font-size: 13px; color: black; text-align: center;">${clusterValue}</div>
        <div style="height: 24px; margin: 0 2px; background-image: url('${iconUrl}'); background-size: 100% 100%;"></div>
      </div>`
      return {
        html: html,
        iconSize: [28, 40],
        iconAnchor: [14, 40],
        riseOnHover: true
      }
    },
    // 获取两个数组中差异项，返回数组
    getDiscardedKey(currentKeys, oldKeys) {
      return currentKeys.concat(oldKeys).filter((value, index, discardedKey) => {
        return discardedKey.indexOf(value) === discardedKey.lastIndexOf(value)
      })
    }
  }
}
</script>

<style lang="less" scoped>
::v-deep .ant-tree {
  // width: 360px;
  height: 672px;
  overflow-y: auto;
  overflow-x: hidden;
}
.map-menu {
  position: absolute;
  // top: 4px;
  right: 4px;
  z-index: 8888;
}
.gd {
  height: 672px;
  position: relative;
}
.icon {
  width: 20px;
  height: 20px;
}
.content {
  display: flex;
  background-color: #fff;
  padding: 12px;
  .left {
    width: 360px;
    min-height: 720px;
    border: 1px solid #e8e8e8;
    margin-top: 14px;
    box-sizing: border-box;
    padding: 18px 12px;
    margin-right: 12px;
  }
  .right {
    width: calc(100% - 372px);
    min-height: 720px;
    margin-top: 14px;
    border: 1px solid #e8e8e8;
    box-sizing: border-box;
    padding: 20px 18px;
  }
}
</style>
